package com.changgou.seckill.service.impl;

import com.alibaba.fastjson.JSON;
import com.changgou.seckill.config.ConfirmMessageSender;
import com.changgou.seckill.config.RabbitMQConfig;
import com.changgou.seckill.dao.SeckillOrderMapper;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.seckill.pojo.SeckillOrder;
import com.changgou.seckill.service.SeckillOrderService;
import com.changgou.util.IdWorker;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author wz
 * @company 公司
 * @create 2020-04-17 17:20
 */
@Service
public class SeckillOrderServiceImpl implements SeckillOrderService {

    @Autowired
    private RedisTemplate redisTemplate;


    public static final String SECKILL_GOODS_KEY="seckill_goods_";

    public static final String SECKILL_GOODS_STOCK_COUNT_KEY="seckill_goods_stock_count_";

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private ConfirmMessageSender confirmMessageSender;

    @Autowired
    private SeckillOrderMapper seckillOrderMapper;
    /**
     * 秒杀下单
     * @param id
     * @param time
     * @param username
     */
    @Override
    public Boolean add(Long id, String time, String username) {
        //防止用户恶意刷单
        String result = this.preventRepeatCommit(username, id);
        if ("fail".equals(result)){
            return false;
        }

        //防止相同商品重复购买
        SeckillOrder order = seckillOrderMapper.getSeckillOrderByUserNameAndGoodsId(username, id);
        if (order !=null ){
            //商品买过
            return false;
        }

        //1.获取redis中的商品信息和库存信息
        SeckillGoods seckillGoods  = (SeckillGoods) redisTemplate.boundHashOps(SECKILL_GOODS_KEY + time).get(id);
        String redisStock = (String) redisTemplate.opsForValue().get(SECKILL_GOODS_STOCK_COUNT_KEY+id);
        //判断redis中的库存是否为null
        if (StringUtils.isEmpty(redisStock)){
            return false;
        }
        //转换为int类型
        Integer stock = Integer.parseInt(redisStock);
        //商品为空，或者库存小于0
        if (seckillGoods == null || stock <=0){
            return false;
        }
        //2.执行redis库存的预扣减操作，并获取扣减之后的库存值  (原子性操作)
        // decrement:减一  也可以多参方法，自定义步长值  increment:加    --> Lua脚本语言（编写redis脚本，也可以保证原子性操作）
        Long decrement = redisTemplate.opsForValue().decrement(SECKILL_GOODS_STOCK_COUNT_KEY + id);
        //3.如果扣减之后的库存值小于等于0，则删除redis中的商品信息和库存信息
        if (decrement<=0){
            //扣减完库存之后，当前商品已经没有库存了
            //删除redis中的商品信息和库存信息
            redisTemplate.boundHashOps(SECKILL_GOODS_KEY + time).delete(id);
            redisTemplate.delete(SECKILL_GOODS_STOCK_COUNT_KEY + id);
        }
        //发送消息，（保证消息生产者对于消息的不丢失实现）
        //消息体：秒杀订单
        SeckillOrder seckillOrder = new SeckillOrder();
        seckillOrder.setId(idWorker.nextId());
        seckillOrder.setSeckillId(id);
        seckillOrder.setMoney(seckillGoods.getCostPrice());
        seckillOrder.setUserId(username);
        seckillOrder.setSellerId(seckillGoods.getSellerId());//商家ID
        seckillOrder.setCreateTime(new Date());
        seckillOrder.setStatus("0");

        //todo
        //4.基于mq完成mysql的数据同步，进行异步下单和扣减库存（更新mysql中的数据）
        confirmMessageSender.sendMessage("", RabbitMQConfig.SECKILL_ORDER_QUUEU, JSON.toJSONString(seckillOrder));
        return true;
    }

    private String preventRepeatCommit(String username,Long id){
        String redis_key="seckill_user_"+username+"_id_"+id;

        long count = redisTemplate.opsForValue().increment(redis_key, 1);

        if (count == 1){
            //代表当前用户第一次访问
            //对当前key设置一个五分钟有效期
            redisTemplate.expire(redis_key,5, TimeUnit.MINUTES);

            return "success";
        }
        if (count>1){
            return "fail";
        }
        return "fail";
    }
}
